﻿#include "lua_mongodb.h"

#include "event_handler.h"
#include "fmt.h"
#include "mongodb/mongodb_query_task.h"
#include "mongodb/mongodb_bulk_task.h"
#include "mongodb/mongodb_mgr.h"

#include <LuaIntf/LuaIntf.h>

#include <functional>

namespace LuaIntf
{
	LUA_USING_LIST_TYPE(std::vector)
}


namespace {

	bool mongo_create_inst(const std::string& dbinst, const std::vector<std::string> &host, std::vector<unsigned> port, const std::string &auth_database, const std::string &user, const std::string &pwd, const std::string &options = "")
	{
		std::string options_ = "";
		if (host.size() > 1)
		{
			options_ = "replicaSet=" + dbinst;
			if (options.size() != 0)
			{
				options_ += "&" + options;
			}
		}
		else
		{
			options_ = options;
		}
		return MongoDbMgr::get_mutable_instance().CreateDbInstance(dbinst, host, port, auth_database, user, pwd, options_);
	}

	void mongo_remove(const std::string& dbinst, const std::string &dbname, const std::string &collection, const std::string &query)
	{
		MongoRemove(dbinst, dbname, collection, query)->Go();
	}

	void mongo_insert(const std::string& dbinst, const std::string &dbname, const std::string &collection, const std::string &doc)
	{
		MongoInsert(dbinst, dbname, collection, doc)->Go();
	}

	void mongo_update(const std::string& dbinst, const std::string &dbname, const std::string &collection, const std::string &query, const std::string &doc)
	{
		MongoUpdate(dbinst, dbname, collection, query, doc)->Go();
	}

	void __mongo_query(uint32_t id, const std::vector<std::string> &retdata)
	{
		std::string lua_event_id = (Fmt("__mongo_query_%u") % id).str();
		EventHandler().Handle(lua_event_id, retdata);
	}

	uint32_t mongo_query(const std::string &dbinst, const std::string &dbname, const std::string &collection, const std::string &query = "{}", const std::string &fields = "")
	{
		static uint32_t g_query_id = 0;
		MongoQuery(dbinst, dbname, collection, query, fields)->SetQueryCB(std::bind(__mongo_query, ++g_query_id, std::placeholders::_1))->Go();
		return g_query_id;
	}

}  // namespace

namespace LuaMongoDb {

	void Bind(lua_State* L)
	{
		assert(L);
		LuaIntf::LuaBinding(L).beginModule("c_mongodb")
			.addFunction("create_inst", &mongo_create_inst)
			.addFunction("remove", &mongo_remove)
			.addFunction("insert", &mongo_insert)
			.addFunction("update", &mongo_update)
			.addFunction("query", &mongo_query)
		.endModule();
	}

}  // namespace LuaMongoDb

